package com.fary.beans.factory.support;

import com.fary.beans.*;
import com.fary.beans.factory.InjectionPoint;
import com.fary.beans.factory.config.AutowireCapableBeanFactory;
import com.fary.beans.factory.config.ConstructorArgumentValues;
import com.fary.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import com.fary.beans.factory.config.DependencyDescriptor;
import com.fary.core.*;
import com.fary.util.*;

import java.beans.ConstructorProperties;
import java.lang.reflect.*;
import java.util.*;

class ConstructorResolver {

    private static final Object[] EMPTY_ARGS = new Object[0];

    private static final NamedThreadLocal<InjectionPoint> currentInjectionPoint = new NamedThreadLocal<>("Current injection point");

    private final AbstractAutowireCapableBeanFactory beanFactory;

    public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {

        BeanWrapperImpl bw = new BeanWrapperImpl();
        this.beanFactory.initBeanWrapper(bw);

        Object factoryBean;
        Class<?> factoryClass;
        boolean isStatic;

        String factoryBeanName = mbd.getFactoryBeanName();
        if (factoryBeanName != null) {
            if (factoryBeanName.equals(beanName)) {
                throw new SpringException(beanName + " factory-bean reference points back to the same bean definition");
            }
            factoryBean = this.beanFactory.getBean(factoryBeanName);
            if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
                throw new IllegalStateException("About-to-be-created singleton instance implicitly appeared through the creation of the factory bean that its bean definition points to");
            }
            factoryClass = factoryBean.getClass();
            isStatic = false;
        } else {
            // It's a static factory method on the bean class.
            if (!mbd.hasBeanClass()) {
                throw new SpringException(beanName + "bean definition declares neither a bean class nor a factory-bean reference");
            }
            factoryBean = null;
            factoryClass = mbd.getBeanClass();
            isStatic = true;
        }

        // 准备使用的工厂方法
        Method factoryMethodToUse = null;
        //准备使用的参数包装器
        ArgumentsHolder argsHolderToUse = null;
        // 准备使用的参数
        Object[] argsToUse = null;

        if (explicitArgs != null) {
            // 如果在调用getBean方法时传入了参数，那么就确定使用该参数
            argsToUse = explicitArgs;
        } else {
            // 解析出的参数
            Object[] argsToResolve = null;
            synchronized (mbd.constructorArgumentLock) {
                // 从缓存中获取，这些缓存的结果是在之后的代码中解析的，使用缓存避免重复解析
                // 获取缓存中的构造方法或者工厂方法
                factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
                // 如果有工厂方法，且构造函数已经解析了
                if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
                    // Found a cached factory method...
                    // 从缓存中获取使用的参数
                    argsToUse = mbd.resolvedConstructorArguments;
                    if (argsToUse == null) {
                        // 获取缓存中的包可见字段
                        argsToResolve = mbd.preparedConstructorArguments;
                    }
                }
            }
            if (argsToResolve != null) {
                //解析对应的缓存数据,对AutowiredArgumentMarker,RuntimeBeanReference等这些占位对象从beanFactory中找到对应的依赖
                argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
            }
        }

        if (factoryMethodToUse == null || argsToUse == null) {
            factoryClass = ClassUtils.getUserClass(factoryClass);
            // 获取所有method
            Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
            List<Method> candidateList = new ArrayList<>();
            for (Method candidate : rawCandidates) {
                // 方法修饰符是否是静态的（和上面的解析是静态工厂还是实例工厂一致）
                if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                    candidateList.add(candidate);
                }
            }

            // 如果只有一个候选方法，那么使用该方法创建bean
            if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
                Method uniqueCandidate = candidateList.get(0);
                if (uniqueCandidate.getParameterCount() == 0) {
                    mbd.factoryMethodToIntrospect = uniqueCandidate;
                    synchronized (mbd.constructorArgumentLock) {
                        mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                        mbd.constructorArgumentsResolved = true;
                        mbd.resolvedConstructorArguments = EMPTY_ARGS;
                    }
                    bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
                    return bw;
                }
            }

            // 不止一个候选方法、getBean有传参数、构造函数无参
            Method[] candidates = candidateList.toArray(new Method[0]);
            //根据修饰符对Method进行排序、public的排在前面，参数多的排在前面
            AutowireUtils.sortFactoryMethods(candidates);

            ConstructorArgumentValues resolvedValues = null;
            boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
            int minTypeDiffWeight = Integer.MAX_VALUE;
            // 模棱两可的工厂方法
            Set<Method> ambiguousFactoryMethods = null;

            // 最小参数个数
            int minNrOfArgs;
            if (explicitArgs != null) {
                minNrOfArgs = explicitArgs.length;
            } else {
                // 我们没有通过编程方式传递参数，因此需要解析在bean定义中保存的构造函数参数中指定的参数。
                if (mbd.hasConstructorArgumentValues()) {
                    ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                    resolvedValues = new ConstructorArgumentValues();
                    minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
                } else {
                    minNrOfArgs = 0;
                }
            }

            // 多个后选方法
            for (Method candidate : candidates) {
                Class<?>[] paramTypes = candidate.getParameterTypes();
                if (paramTypes.length >= minNrOfArgs) {
                    ArgumentsHolder argsHolder;
                    if (explicitArgs != null) {
                        // 给定的显式参数 -> 参数长度必须完全匹配。
                        if (paramTypes.length != explicitArgs.length) {
                            continue;
                        }
                        argsHolder = new ArgumentsHolder(explicitArgs);
                    } else {
                        try {
                            String[] paramNames = null;
                            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                            if (pnd != null) {
                                paramNames = pnd.getParameterNames(candidate);
                            }
                            argsHolder = createArgumentArray(beanName, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
                        } catch (SpringException ex) {
                            continue;
                        }
                    }

                    int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                    // Choose this factory method if it represents the closest match.
                    if (typeDiffWeight < minTypeDiffWeight) {
                        factoryMethodToUse = candidate;
                        argsHolderToUse = argsHolder;
                        argsToUse = argsHolder.arguments;
                        minTypeDiffWeight = typeDiffWeight;
                        ambiguousFactoryMethods = null;
                    }
                    // Find out about ambiguity: In case of the same type difference weight
                    // for methods with the same number of parameters, collect such candidates
                    // and eventually raise an ambiguity exception.
                    // However, only perform that check in non-lenient constructor resolution mode,
                    // and explicitly ignore overridden methods (with the same parameter signature).
                    else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
                            !mbd.isLenientConstructorResolution() &&
                            paramTypes.length == factoryMethodToUse.getParameterCount() &&
                            !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
                        if (ambiguousFactoryMethods == null) {
                            ambiguousFactoryMethods = new LinkedHashSet<>();
                            ambiguousFactoryMethods.add(factoryMethodToUse);
                        }
                        ambiguousFactoryMethods.add(candidate);
                    }
                }
            }

            if (factoryMethodToUse == null) {
                List<String> argTypes = new ArrayList<>(minNrOfArgs);
                if (explicitArgs != null) {
                    for (Object arg : explicitArgs) {
                        argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
                    }
                } else if (resolvedValues != null) {
                    Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
                    valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
                    valueHolders.addAll(resolvedValues.getGenericArgumentValues());
                    for (ValueHolder value : valueHolders) {
                        String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
                                (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
                        argTypes.add(argType);
                    }
                }
                throw new SpringException(beanName + "No matching factory method found: " + (mbd.getFactoryBeanName() != null ? "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
                        "factory method '" + mbd.getFactoryMethodName() + "Check that a method with the specified name " +
                        (minNrOfArgs > 0 ? "and arguments " : "") + "exists and that it is " + (isStatic ? "static" : "non-static") + ".");
            } else if (void.class == factoryMethodToUse.getReturnType()) {
                throw new SpringException(beanName + " Invalid factory method '" + mbd.getFactoryMethodName() + "': needs to have a non-void return type!");
            } else if (ambiguousFactoryMethods != null) {
                throw new SpringException(beanName + " Ambiguous factory method matches found in bean '" + beanName + "' " +
                        "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousFactoryMethods);
            }

            if (explicitArgs == null && argsHolderToUse != null) {
                mbd.factoryMethodToIntrospect = factoryMethodToUse;
                argsHolderToUse.storeCache(mbd, factoryMethodToUse);
            }
        }

        Assert.state(argsToUse != null, "Unresolved factory method arguments");
        bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
        return bw;
    }

    private Method[] getCandidateMethods(Class<?> factoryClass, RootBeanDefinition mbd) {
        return (mbd.isNonPublicAccessAllowed() ? ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
    }

    private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, Executable executable, Object[] argsToResolve, boolean fallback) {
        TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
        TypeConverter converter = (customConverter != null ? customConverter : bw);
        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
        Class<?>[] paramTypes = executable.getParameterTypes();

        Object[] resolvedArgs = new Object[argsToResolve.length];
        for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
            Object argValue = argsToResolve[argIndex];
            MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
            GenericTypeResolver.resolveParameterType(methodParam, executable.getDeclaringClass());
            if (argValue instanceof AutowiredArgumentMarker) {
                argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, fallback);
            } else if (argValue instanceof BeanMetadataElement) {
                argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
            } else if (argValue instanceof String) {
                argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
            }
            Class<?> paramType = paramTypes[argIndex];
            try {
                resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
            } catch (SpringException ex) {
                throw new SpringException(beanName + " Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
            }
        }
        return resolvedArgs;
    }

    private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {

        // 1.构建bean定义值解析器
        TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
        TypeConverter converter = (customConverter != null ? customConverter : bw);
        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);

        // 2.minNrOfArgs初始化为indexedArgumentValues和genericArgumentValues的的参数个数总和
        int minNrOfArgs = cargs.getArgumentCount();
        // 3.遍历解析带index的参数值
        for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
            int index = entry.getKey();
            if (index < 0) {
                throw new SpringException(beanName + " Invalid constructor argument index: " + index);
            }
            // 3.1 如果index大于minNrOfArgs，则修改minNrOfArgs
            if (index > minNrOfArgs) {
                // index是从0开始，并且是有序递增的，所以当有参数的index=5时，代表该方法至少有6个参数
                minNrOfArgs = index + 1;
            }
            ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
            // 3.2 解析参数值
            if (valueHolder.isConverted()) {
                // 3.2.1 如果参数值已经转换过，则直接将index和valueHolder添加到resolvedValues的indexedArgumentValues属性
                resolvedValues.addIndexedArgumentValue(index, valueHolder);
            } else {
                // 3.2.2 如果值还未转换过，则先进行转换
                Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
                // 3.2.3 使用转换后的resolvedValue构建新的ValueHolder
                ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
                // 3.2.4 将转换前的valueHolder保存到新的ValueHolder的source属性
                resolvedValueHolder.setSource(valueHolder);
                // 3.2.5 将index和新的ValueHolder添加到resolvedValues的indexedArgumentValues属性
                resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
            }
        }

        // 4.遍历解析通用参数值（不带index）
        for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
            if (valueHolder.isConverted()) {
                // 4.1 如果参数值已经转换过，则直接将valueHolder添加到resolvedValues的genericArgumentValues属性
                resolvedValues.addGenericArgumentValue(valueHolder);
            } else {
                // 4.2 如果值还未转换过，则先进行转换
                Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
                // 4.3 使用转换后的resolvedValue构建新的ValueHolder
                ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
                // 4.4 将转换前的valueHolder保存到新的ValueHolder的source属性
                resolvedValueHolder.setSource(valueHolder);
                // 4.5 将新的ValueHolder添加到resolvedValues的genericArgumentValues属性
                resolvedValues.addGenericArgumentValue(resolvedValueHolder);
            }
        }
        // 5.返回构造函数参数的个数
        return minNrOfArgs;
    }

    private ArgumentsHolder createArgumentArray(String beanName, ConstructorArgumentValues resolvedValues, BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Executable executable, boolean autowiring, boolean fallback) throws SpringException {

        TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
        // 获取类型转换器
        TypeConverter converter = (customConverter != null ? customConverter : bw);
        // 新建一个ArgumentsHolder来存放匹配到的参数
        ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
        Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
        Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
        // 1.遍历参数类型数组
        for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
            // 拿到当前遍历的参数类型
            Class<?> paramType = paramTypes[paramIndex];
            // 拿到当前遍历的参数名
            String paramName = (paramNames != null ? paramNames[paramIndex] : "");
            // 2.查找当前遍历的参数，是否在mdb对应的bean的构造函数参数中存在index、类型和名称匹配的
            ConstructorArgumentValues.ValueHolder valueHolder = null;
            if (resolvedValues != null) {
                valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
                // 3.如果我们找不到直接匹配并且不应该自动装配，那么让我们尝试下一个通用的无类型参数值作为降级方法：它可以在类型转换后匹配（例如，String - > int）。
                if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
                    valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
                }
            }
            if (valueHolder != null) {
                // 4.valueHolder不为空，存在匹配的参数
                usedValueHolders.add(valueHolder);
                // 原始属性值
                Object originalValue = valueHolder.getValue();
                // 转换后的属性值
                Object convertedValue;
                if (valueHolder.isConverted()) {
                    // 4.1 如果valueHolder已经转换过
                    // 4.1.1 则直接获取转换后的值
                    convertedValue = valueHolder.getConvertedValue();
                    // 4.1.2 将convertedValue作为args在paramIndex位置的预备参数
                    args.preparedArguments[paramIndex] = convertedValue;
                } else {
                    // 4.2.3 将方法（此处为构造函数）和参数索引封装成MethodParameter(MethodParameter是封装方法和参数索引的工具类)
                    MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
                    try {
                        // 4.2.4 将原始值转换为paramType类型的值（如果类型无法转，抛出TypeMismatchException）
                        convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
                    } catch (SpringException ex) {
                        throw new SpringException(beanName + " Could not convert argument value of type [" + valueHolder.getValue() + "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
                    }
                    // 4.2.2 拿到原始参数值
                    Object sourceHolder = valueHolder.getSource();
                    if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
                        Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
                        // 4.2.5 args标记为需要解析
                        args.resolveNecessary = true;
                        // 4.2.6 将convertedValue作为args在paramIndex位置的预备参数
                        args.preparedArguments[paramIndex] = sourceValue;
                    }
                }
                // 4.3 将convertedValue作为args在paramIndex位置的参数
                args.arguments[paramIndex] = convertedValue;
                // 4.4 将originalValue作为args在paramIndex位置的原始参数
                args.rawArguments[paramIndex] = originalValue;
            } else {
                // 5.valueHolder为空，不存在匹配的参数
                // 5.1 将方法（此处为构造函数）和参数索引封装成MethodParameter
                MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
                // 5.2 找不到明确的匹配，并且不是自动装配，则抛出异常
                if (!autowiring) {
                    throw new SpringException(beanName + " Ambiguous argument values for parameter of type [" + paramType.getName() + "] - did you specify the correct bean references as arguments?");
                }
                try {
                    // 5.3 如果是自动装配，则调用用于解析自动装配参数的方法，返回的结果为依赖的bean实例对象
                    // 例如：@Autowire修饰构造函数，自动注入构造函数中的参数bean就是在这边处理
                    Object autowiredArgument = resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter, fallback);
                    args.rawArguments[paramIndex] = autowiredArgument;
                    args.arguments[paramIndex] = autowiredArgument;
                    args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
                    args.resolveNecessary = true;
                } catch (SpringException ex) {
                    // 4.2.7 如果类型转换失败，则抛出异常
                    throw new SpringException(beanName, ex);
                }
            }
        }

        for (String autowiredBeanName : autowiredBeanNames) {
            this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
        }

        return args;
    }

    protected Object resolveAutowiredArgument(MethodParameter param, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {

        // 1.如果参数类型为InjectionPoint
        Class<?> paramType = param.getParameterType();
        if (InjectionPoint.class.isAssignableFrom(paramType)) {
            // 1.1 拿到当前的InjectionPoint（存储了当前正在解析依赖的方法参数信息，DependencyDescriptor）
            InjectionPoint injectionPoint = currentInjectionPoint.get();
            // 1.2 当前injectionPoint为空，则抛出异常：目前没有可用的InjectionPoint
            if (injectionPoint == null) {
                throw new IllegalStateException("No current InjectionPoint available for " + param);
            }
            // 1.3 返回当前的InjectionPoint
            return injectionPoint;
        }
        try {
            // 2.解析指定依赖，DependencyDescriptor：将MethodParameter的方法参数索引信息封装成DependencyDescriptor
            return this.beanFactory.resolveDependency(new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
        } catch (SpringException ex) {
            if (fallback) {
                // Single constructor or factory method -> let's return an empty array/collection
                // for e.g. a vararg or a non-null List/Set/Map parameter.
                if (paramType.isArray()) {
                    return Array.newInstance(paramType.getComponentType(), 0);
                } else if (CollectionFactory.isApproximableCollectionType(paramType)) {
                    return CollectionFactory.createCollection(paramType, 0);
                } else if (CollectionFactory.isApproximableMapType(paramType)) {
                    return CollectionFactory.createMap(paramType, 0);
                }
            }
            throw ex;
        }
    }

    public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, Constructor<?>[] chosenCtors, Object[] explicitArgs) {
        // 定义bean包装类
        BeanWrapperImpl bw = new BeanWrapperImpl();
        this.beanFactory.initBeanWrapper(bw);
        // 最终用于实例化的构造函数
        Constructor<?> constructorToUse = null;
        // 最终用于实例化的参数Holder
        ArgumentsHolder argsHolderToUse = null;
        // 最终用于实例化的构造函数参
        Object[] argsToUse = null;
        // 1.解析出要用于实例化的构造函数参数
        if (explicitArgs != null) {
            // 1.1 如果explicitArgs不为空，则构造函数的参数直接使用explicitArgs
            // 通过getBean方法调用时，显示指定了参数，则explicitArgs就不为null
            argsToUse = explicitArgs;
        } else {
            // 1.2 尝试从缓存中获取已经解析过的构造函数参数
            Object[] argsToResolve = null;
            synchronized (mbd.constructorArgumentLock) {
                // 1.2.1 拿到缓存中已解析的构造函数或工厂方法
                constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
                if (constructorToUse != null && mbd.constructorArgumentsResolved) {
                    // 1.2.3 从缓存中获取已解析的构造函数参数
                    argsToUse = mbd.resolvedConstructorArguments;
                    if (argsToUse == null) {
                        // 1.2.4 如果resolvedConstructorArguments为空，则从缓存中获取准备用于解析的构造函数参数，
                        // constructorArgumentsResolved为true时，resolvedConstructorArguments和
                        // preparedConstructorArguments必然有一个缓存了构造函数的参数
                        argsToResolve = mbd.preparedConstructorArguments;
                    }
                }
            }
            if (argsToResolve != null) {
                // 1.2.5 如果argsToResolve不为空，则对构造函数参数进行解析，
                // 如给定方法的构造函数 A(int,int)则通过此方法后就会把配置中的("1","1")转换为(1,1)
                argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
            }
        }

        // 2.如果构造函数没有被缓存，则通过配置文件获取
        if (constructorToUse == null || argsToUse == null) {

            // 3.确认构造函数的候选者
            // 3.1 如果入参chosenCtors不为空，则将chosenCtors的构造函数作为候选者
            Constructor<?>[] candidates = chosenCtors;
            if (candidates == null) {
                Class<?> beanClass = mbd.getBeanClass();
                try {
                    // 3.2 如果入参chosenCtors为空，则获取beanClass的构造函数
                    // （mbd是否允许访问非公共构造函数和方法 ? 所有声明的构造函数：公共构造函数）
                    candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());
                } catch (Throwable ex) {
                    throw new SpringException(beanName + " Resolution of declared constructors on bean Class [" + beanClass.getName() + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                }
            }

            if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
                Constructor<?> uniqueCandidate = candidates[0];
                if (uniqueCandidate.getParameterCount() == 0) {
                    synchronized (mbd.constructorArgumentLock) {
                        mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                        mbd.constructorArgumentsResolved = true;
                        mbd.resolvedConstructorArguments = EMPTY_ARGS;
                    }
                    bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
                    return bw;
                }
            }

            // Need to resolve the constructor.
            // 2.1 检查是否需要自动装配：chosenCtors不为空 || autowireMode为AUTOWIRE_CONSTRUCTOR
            // 例子：当chosenCtors不为空时，代表有构造函数通过@Autowire修饰，因此需要自动装配
            boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
            ConstructorArgumentValues resolvedValues = null;

            // 构造函数参数个数
            int minNrOfArgs;
            if (explicitArgs != null) {
                // 2.2 explicitArgs不为空，则使用explicitArgs的length作为minNrOfArgs的值
                minNrOfArgs = explicitArgs.length;
            } else {
                // 2.3 获得mbd的构造函数的参数值（indexedArgumentValues：带index的参数值；genericArgumentValues：通用的参数值）
                ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                // 2.4 创建ConstructorArgumentValues对象resolvedValues，用于承载解析后的构造函数参数的值
                resolvedValues = new ConstructorArgumentValues();
                // 2.5 解析mbd的构造函数的参数，并返回参数个数
                minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
                // 注：这边解析mbd中的构造函数参数值，主要是处理我们通过xml方式定义的构造函数注入的参数，
                // 但是如果我们是通过@Autowire注解直接修饰构造函数，则mbd是没有这些参数值的
            }


            // 3.3 对给定的构造函数排序：先按方法修饰符排序：public排非public前面，再按构造函数参数个数排序：参数多的排前面
            AutowireUtils.sortConstructors(candidates);
            // 最小匹配权重，权重越小，越接近我们要找的目标构造函数
            int minTypeDiffWeight = Integer.MAX_VALUE;
            Set<Constructor<?>> ambiguousConstructors = null;

            // 4.遍历所有构造函数候选者，找出符合条件的构造函数
            for (Constructor<?> candidate : candidates) {
                // 4.1 拿到当前遍历的构造函数的参数类型数组
                Class<?>[] paramTypes = candidate.getParameterTypes();

                if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
                    // 4.2 如果已经找到满足的构造函数 && 目标构造函数需要的参数个数大于当前遍历的构造函数的参数个数则终止，
                    // 因为遍历的构造函数已经排过序，后面不会有更合适的候选者了
                    break;
                }
                if (paramTypes.length < minNrOfArgs) {
                    // 4.3 如果当前遍历到的构造函数的参数个数小于我们所需的参数个数，则直接跳过该构造函数
                    continue;
                }

                ArgumentsHolder argsHolder;
                if (resolvedValues != null) {
                    // 存在参数则根据参数值来匹配参数类型
                    try {
                        // 4.4 resolvedValues不为空，
                        // 4.4.1 获取当前遍历的构造函数的参数名称
                        // 4.4.1.1 解析使用ConstructorProperties注解的构造函数参数
                        String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
                        if (paramNames == null) {
                            // 4.4.1.2 获取参数名称解析器
                            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                            if (pnd != null) {
                                // 4.4.1.3 使用参数名称解析器获取当前遍历的构造函数的参数名称
                                paramNames = pnd.getParameterNames(candidate);
                            }
                        }
                        // 4.4.2 创建一个参数数组以调用构造函数或工厂方法，
                        // 主要是通过参数类型和参数名解析构造函数或工厂方法所需的参数（如果参数是其他bean，则会解析依赖的bean）
                        argsHolder = createArgumentArray(beanName, resolvedValues, bw, paramTypes, paramNames, getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
                    } catch (SpringException ex) {
                        continue;
                    }
                } else {
                    // 4.5 resolvedValues为空，则explicitArgs不为空，即给出了显式参数
                    // Explicit arguments given -> arguments length must match exactly.
                    // 4.5.1 如果当前遍历的构造函数参数个数与explicitArgs长度不相同，则跳过该构造函数
                    if (paramTypes.length != explicitArgs.length) {
                        continue;
                    }
                    // 4.5.2 使用显式给出的参数构造ArgumentsHolder
                    argsHolder = new ArgumentsHolder(explicitArgs);
                }

                // 4.6 根据mbd的解析构造函数模式（true: 宽松模式(默认)，false：严格模式），
                // 将argsHolder的参数和paramTypes进行比较，计算paramTypes的类型差异权重值
                int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                // Choose this constructor if it represents the closest match.
                // 4.7 类型差异权重值越小,则说明构造函数越匹配，则选择此构造函数
                if (typeDiffWeight < minTypeDiffWeight) {
                    // 将要使用的参数都替换成差异权重值更小的
                    constructorToUse = candidate;
                    argsHolderToUse = argsHolder;
                    argsToUse = argsHolder.arguments;
                    minTypeDiffWeight = typeDiffWeight;
                    // 如果出现权重值更小的候选者，则将ambiguousConstructors清空，允许之前存在权重值相同的候选者
                    ambiguousConstructors = null;
                } else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
                    // 4.8 如果存在两个候选者的权重值相同，并且是当前遍历过权重值最小的
                    // 将这两个候选者都添加到ambiguousConstructors
                    if (ambiguousConstructors == null) {
                        ambiguousConstructors = new LinkedHashSet<>();
                        ambiguousConstructors.add(constructorToUse);
                    }
                    ambiguousConstructors.add(candidate);
                }
            }

            if (constructorToUse == null) {
                // 5.如果最终没有找到匹配的构造函数，则进行异常处理
                throw new SpringException(beanName + "Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
            } else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
                // 6.如果找到了匹配的构造函数，但是存在多个（ambiguousConstructors不为空） && 解析构造函数的模式为严格模式，则抛出异常
                throw new SpringException(beanName + "Ambiguous constructor matches found in bean '" + beanName + "' (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousConstructors);
            }

            if (explicitArgs == null && argsHolderToUse != null) {
                // 7.将解析的构造函数和参数放到缓存
                argsHolderToUse.storeCache(mbd, constructorToUse);
            }
        }
        Assert.state(argsToUse != null, "Unresolved constructor arguments");
        // 8.根据实例化策略以及得到的构造函数及构造函数参数实例化bean
        // 9.将构造的实例加入BeanWrapper中，并返回
        bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
        return bw;
    }

    static InjectionPoint setCurrentInjectionPoint(InjectionPoint injectionPoint) {
        InjectionPoint old = currentInjectionPoint.get();
        if (injectionPoint != null) {
            currentInjectionPoint.set(injectionPoint);
        } else {
            currentInjectionPoint.remove();
        }
        return old;
    }

    protected Constructor<?> getUserDeclaredConstructor(Constructor<?> constructor) {
        Class<?> declaringClass = constructor.getDeclaringClass();
        Class<?> userClass = ClassUtils.getUserClass(declaringClass);
        if (userClass != declaringClass) {
            try {
                return userClass.getDeclaredConstructor(constructor.getParameterTypes());
            } catch (NoSuchMethodException ex) {
                // No equivalent constructor on user class (superclass)...
                // Let's proceed with the given constructor as we usually would.
            }
        }
        return constructor;
    }

    public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
        Class<?> factoryClass;
        boolean isStatic;
        if (mbd.getFactoryBeanName() != null) {
            factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
            isStatic = false;
        } else {
            factoryClass = mbd.getBeanClass();
            isStatic = true;
        }
        Assert.state(factoryClass != null, "Unresolvable factory class");
        factoryClass = ClassUtils.getUserClass(factoryClass);

        Method[] candidates = getCandidateMethods(factoryClass, mbd);
        Method uniqueCandidate = null;
        for (Method candidate : candidates) {
            if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                if (uniqueCandidate == null) {
                    uniqueCandidate = candidate;
                } else if (!Arrays.equals(uniqueCandidate.getParameterTypes(), candidate.getParameterTypes())) {
                    uniqueCandidate = null;
                    break;
                }
            }
        }
        mbd.factoryMethodToIntrospect = uniqueCandidate;
    }

    private Object instantiate(String beanName, RootBeanDefinition mbd, Constructor constructorToUse, Object[] argsToUse) {
        try {
            InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
            return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
        } catch (Throwable ex) {
            throw new SpringException(beanName + " Bean instantiation via constructor failed", ex);
        }
    }

    private Object instantiate(String beanName, RootBeanDefinition mbd, Object factoryBean, Method factoryMethod, Object[] args) {
        try {
            InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
            return strategy.instantiate(mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
        } catch (Throwable ex) {
            throw new SpringException(beanName + " Bean instantiation via factory method failed", ex);
        }
    }


    private static class ArgumentsHolder {

        // 原生的参数类型，没有进行过类型转换的参数，其主要是用来计算构造器的差异权重
        public final Object[] rawArguments;
        // 进行过类型转换后的参数，这个参数是真正传给构造器方法调用的参数，它也用来计算差异权重的
        public final Object[] arguments;
        // 准备的参数，这个参数是对于需要进行动态解析的参数以及需要进行类型转换的参数缓存时存储在这个属性中，
        // 再次进行参数实例化则对这个参数进行解析出对应的真正参数传递给构造器使用
        public final Object[] preparedArguments;
        // 这个是标识参数需要进行解析，在将缓存存储到RootBeanDefinition中是缓存preparedArguments还是直接缓存arguments的标识
        public boolean resolveNecessary = false;

        public ArgumentsHolder(int size) {
            this.rawArguments = new Object[size];
            this.arguments = new Object[size];
            this.preparedArguments = new Object[size];
        }

        public ArgumentsHolder(Object[] args) {
            this.rawArguments = args;
            this.arguments = args;
            this.preparedArguments = args;
        }

        public int getTypeDifferenceWeight(Class<?>[] paramTypes) {
            // 如果找到有效的参数，确定类型差异权重。
            // 在被转换的参数和变量上尝试类型差异权重
            // 原始参数。如果原始重量更好，就使用它。
            // 减少原始权重1024，以优先于相等的转换权重。
            int typeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.arguments);
            int rawTypeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;
            return Math.min(rawTypeDiffWeight, typeDiffWeight);
        }

        public int getAssignabilityWeight(Class<?>[] paramTypes) {
            for (int i = 0; i < paramTypes.length; i++) {
                if (!ClassUtils.isAssignableValue(paramTypes[i], this.arguments[i])) {
                    return Integer.MAX_VALUE;
                }
            }
            for (int i = 0; i < paramTypes.length; i++) {
                if (!ClassUtils.isAssignableValue(paramTypes[i], this.rawArguments[i])) {
                    return Integer.MAX_VALUE - 512;
                }
            }
            return Integer.MAX_VALUE - 1024;
        }

        public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
            synchronized (mbd.constructorArgumentLock) {
                // 将构造函数或工厂方法放到resolvedConstructorOrFactoryMethod缓存
                mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
                // constructorArgumentsResolved标记为已解析
                mbd.constructorArgumentsResolved = true;
                if (this.resolveNecessary) {
                    // 如果参数需要解析，则将preparedArguments放到preparedConstructorArguments缓存
                    mbd.preparedConstructorArguments = this.preparedArguments;
                } else {
                    // 如果参数不需要解析，则将arguments放到resolvedConstructorArguments缓存
                    mbd.resolvedConstructorArguments = this.arguments;
                }
            }
        }
    }

    private static class AutowiredArgumentMarker {
    }

    private static class ConstructorPropertiesChecker {
        public static String[] evaluate(Constructor<?> candidate, int paramCount) {
            ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
            if (cp != null) {
                String[] names = cp.value();
                if (names.length != paramCount) {
                    throw new IllegalStateException("Constructor annotated with @ConstructorProperties but not " +
                            "corresponding to actual number of parameters (" + paramCount + "): " + candidate);
                }
                return names;
            } else {
                return null;
            }
        }
    }
}